import {data as musicKeyValues} from "../data/music-key-value";
import {getMusicNameByValue, getMusicNameValue} from "../data/music-name-value";
import {data as intervalData} from "../data/music-interval";
import {compareKey, deepCopyProperties, hasEmpty, multiCompare, singleCompare, toast} from "./common";
import {seventh, triad} from "../data/music-chord";

// 根据x y值获取音符
export function getMusicFlagByXYValue(xValue, yValue) {
    let item = musicKeyValues.find(item => (item.yValue === (yValue.toString())) && (item.xValue === xValue.toString()));
    return item ? {name: (item.level + ' ' + item.musicName + item.groupLevel), ...item} : null;
}

// 根据x y值获取音符
export function getMusicFlagByMusicNameYValue(musicName, yValue) {
    let item = musicKeyValues.find(item => (item.yValue === (yValue.toString())) && (item.musicName.toLowerCase() === musicName.toString().toLowerCase()));
    return item ? {name: (item.level + ' ' + item.musicName + item.groupLevel), ...item} : null;
}
// 根据x y增加一个八度
export function addEightByXYValue(xValue, yValue) {
    let currentIndex = -1;
    musicKeyValues.find((item, index) => {
        if ((item.yValue === (yValue + '')) && (item.xValue === xValue)) {
            currentIndex = index;
            return item;
        }
    });
    if (currentIndex === -1) return null;
    //如果是大字组
    let nextIndex = currentIndex + 35;
    if (nextIndex >= musicKeyValues.length || nextIndex < 0) return null;
    let nextEight = musicKeyValues[nextIndex];
    return {name: (nextEight.level + ' ' + nextEight.musicName + nextEight.groupLevel), ...nextEight};
}

// 根据x y减去一个八度
export function subEightByXYValue(xValue, yValue) {
    let currentIndex = -1;
    musicKeyValues.find((item, index) => {
        if ((item.yValue === (yValue + '')) && (item.xValue === xValue)) {
            currentIndex = index;
            return item;
        }
    });
    if (currentIndex === -1) return null;
    //如果是大字组
    let nextIndex = currentIndex - 35;
    if (nextIndex >= musicKeyValues.length || nextIndex < 0) return null;
    let nextEight = musicKeyValues[nextIndex];
    return {name: (nextEight.level + ' ' + nextEight.musicName + nextEight.groupLevel), ...nextEight};
}

// 根据x y获取音程
export function getInterval(xValue, yValue) {
    let res = intervalData.find(item => item.xValue === xValue.toString() && item.yValue === yValue.toString());
    return res ? res.result : undefined;
}

//取两音之间的音程
export function computeInterval(xValue1, yValue1, xValue2, yValue2, isChord = false) {
    //把音名转换为数字
    let format_xValue1 = +xValue1
    let format_xValue2 = +xValue2;
    //1音减去2音
    let xValue = yValue1 > yValue2 || isChord ? (format_xValue1 - format_xValue2) : (format_xValue2 - format_xValue1);
    let yValue = yValue1 > yValue2 || isChord ? (+yValue1 - +yValue2) : (+yValue2 - +yValue1);
    let count = (yValue < 0 || yValue > 12) ? -1 : 0;
    let result = undefined;
    //判断是否有负数结果
    while (xValue < 0) xValue += 7;
    //如果大于7就减到小于7
    while (xValue > 7) xValue -= 7;
    while (yValue < 0) {
        count++;
        yValue += 12;
    }
    //先做一次匹配
    //匹配音程
    result = getInterval(xValue, yValue);
    while (yValue > 12) {
        count++;
        yValue -= 12;
    }
    let scale = count * 7
    if (!result)
        //匹配音程
        result = getInterval(xValue, yValue);
    // toast(result);
    return result ? (result.replace(/\d/g, old => {
        return scale + +old;
    })) : undefined;
}

//根据音程名取音程对象
export function getIntervalByIntervalName(intervalName) {
    return intervalData.find(item => item.result === intervalName) || null
}

//根据1音和度数求另一个音
export function getByInterval(position, key, interval) {
    //取音名
    let format_xValue1 = getMusicNameValue(key.musicName);
    if (!format_xValue1) return format_xValue1;
    //根据音程名取音程x y值
    let result = getIntervalByIntervalName(interval);
    if (!result) return result;
    let format_xValue2 = result.xValue;
    let yValue1 = key.yValue;
    let yValue2 = result.yValue;
    let res = undefined;
    if (position === '上方') {
        //上方音程
        //1音加上音程
        let xValue = +format_xValue2 + +format_xValue1;
        let yValue = +yValue1 + +yValue2;
        //判断是否有过剩结果
        while (xValue > 7) xValue -= 7;
        xValue = getMusicNameByValue(xValue + '');
        //根据x y值取对应的音
        res = getMusicFlagByMusicNameYValue(xValue, yValue) || undefined;
    } else {
        //下方音程
        //上方音程
        //1音减去音程
        let xValue = yValue1 > yValue2 ? (format_xValue1 - format_xValue2) : (format_xValue2 - format_xValue1);
        let yValue = yValue1 > yValue2 ? (+yValue1 - +yValue2) : (+yValue2 - +yValue1);
        //判断是否有过剩结果
        while (xValue < 0) xValue += 7;
        while (yValue < 0) yValue += 12;
        // while (yValue > 12) yValue -= 12;
        // toast(xValue+'---'+yValue)
        xValue = getMusicNameByValue(xValue + '');
        //根据x y值取对应的音
        res = getMusicFlagByMusicNameYValue(xValue, yValue) || undefined;
    }
    if (!res) {
        toast('无法通过该音程和音取得对应的音');
    } else {
        return res;
    }
}

//将传入进来的音数组根据和弦排列重新排序
export function sortByChordRules(...key) {
    if (!key || key.length < 1) return null;
    let result = undefined;
    //根据音名重新排列顺序
    if (key.length === 3) {
        //三和弦排序表
        let triadRule = [
            'ceg', 'egb', 'gbd', 'bdf', 'dfa', 'fac', 'ace'
        ]
        //判断三个音是否符合排序表中的同一组结果
        result = triadRule.find(item =>
            item.indexOf(key[0].musicName.toLowerCase()) !== -1 &&
            item.indexOf(key[1].musicName.toLowerCase()) !== -1 &&
            item.indexOf(key[2].musicName.toLowerCase()) !== -1
        )
    } else if (key.length === 4) {
        //七和弦排序表
        let seventhRule = [
            'cegb', 'egbd', 'gbdf', 'bdfa', 'dfac', 'face', 'aceg'
        ]
        //判断三个音是否符合排序表中的同一组结果
        result = seventhRule.find(item =>
            item.indexOf(key[0].musicName.toLowerCase()) !== -1 &&
            item.indexOf(key[1].musicName.toLowerCase()) !== -1 &&
            item.indexOf(key[2].musicName.toLowerCase()) !== -1 &&
            item.indexOf(key[3].musicName.toLowerCase()) !== -1
        )
    }
    if (!result) return result;
    //给予键一个排序号
    key.forEach(item => item.sortId = result.indexOf(item.musicName.toLowerCase()));
    return key.sort(singleCompare('sortId'));
}

//已知三音求性质及三和弦
export function getTriad(first, second, third) {
    //排序
    let sortedKeys = sortByChordRules(first, second, third);
    if (!sortedKeys || sortedKeys.length < 3) return undefined;
    //取根音
    let rootKey = sortedKeys[0];
    //取三音
    let thirdKey = sortedKeys[1];
    //取五音
    let fifthKey = sortedKeys[2];
    //计算三音-根音的音程
    let firstIntervalName = computeInterval(thirdKey.xValue, thirdKey.yValue, rootKey.xValue, rootKey.yValue, true);
    //计算五音-三音的音程
    let secondIntervalName = computeInterval(fifthKey.xValue, fifthKey.yValue, thirdKey.xValue, thirdKey.yValue, true);
    if (hasEmpty(firstIntervalName, secondIntervalName)) return undefined;
    //根据音程获取对应三和弦
    let result = triad.find(item => item.first === firstIntervalName && item.third === secondIntervalName)
    if (!result) return undefined;
    result = result.name;
    let minKey = deepCopyProperties(sortedKeys).sort(singleCompare('sortId'))
    if (!minKey || minKey.length < 1) return undefined;
    let min = minKey[0]; //低音
    if (compareKey(min, thirdKey)) {
        //如果三音为低音,就是六和弦
        result = result.replace('三和弦', '六和弦');
    } else if (compareKey(min, fifthKey)) {
        //如果五音为低音,就是四六和弦
        result = result.replace('三和弦', '四六和弦');
    }
    return result;
}

//已知四音求性质及七和弦
export function getSeventh(first, second, third, fourth) {
    //排序
    let sortedKeys = sortByChordRules(first, second, third, fourth);
    if (!sortedKeys || sortedKeys.length < 4) return undefined;
    //取根音
    let rootKey = sortedKeys[0];
    //取三音
    let thirdKey = sortedKeys[1];
    //取五音
    let fifthKey = sortedKeys[2];
    //取七音
    let seventhKey = sortedKeys[3];
    //计算三音-根音的音程
    let firstIntervalName = computeInterval(thirdKey.xValue, thirdKey.yValue, rootKey.xValue, rootKey.yValue, true);
    //计算五音-三音的音程
    let secondIntervalName = computeInterval(fifthKey.xValue, fifthKey.yValue, thirdKey.xValue, thirdKey.yValue, true);
    //计算七音-五音的音程
    let thirdIntervalName = computeInterval(seventhKey.xValue, seventhKey.yValue, fifthKey.xValue, fifthKey.yValue, true);
    if (hasEmpty(firstIntervalName, secondIntervalName, thirdIntervalName)) return undefined;
    // toast(firstIntervalName+secondIntervalName+thirdIntervalName)
    //根据音程获取对应三和弦
    let result = seventh.find(item => item.first === firstIntervalName && item.third === secondIntervalName && item.fifth === thirdIntervalName)
    if (!result) return undefined;
    result = result.name;
    let minKey = deepCopyProperties(sortedKeys).sort(singleCompare('sortId'))
    if (!minKey || minKey.length < 1) return undefined;
    let min = minKey[0]; //低音
    if (compareKey(min, thirdKey)) {
        //如果三音为低音,就是六和弦
        result = result.replace('七和弦', '五六和弦');
    } else if (compareKey(min, fifthKey)) {
        //如果五音为低音,就是四六和弦
        result = result.replace('七和弦', '三四和弦');
    } else if (compareKey(min, seventhKey)) {
        //如果七音为低音,就是二和弦
        result = result.replace('七和弦', '二和弦');
    }
    return result;
}

//获取某个音的所有同组等音
export function getSameSoundKey(key) {
    if (!key) return undefined;
    let sameSounds = [];
    musicKeyValues.forEach(item => {
        //如果y值相等，说明是同等音高
        if (!compareKey(item, key) && item.yValue === key.yValue && item.groupLevelName === key.groupLevelName) {
            sameSounds.push(getMusicFlagByXYValue(item.xValue, item.yValue));
        }
    });
    return sameSounds;
}
